import UIKit
// 向已有的类，结构体，枚举添加新功能。与OC的category类似
/**
 1.添加计算属性和静态计算属性
 2.定义实例方法和类型方法
 3.提供新的构造器
 4.定义下标
 5.定义和使用新的嵌套类型
 6.使用一个已有类型符合某个协议
 extesion SomeType{
 }
 
 //在扩展中添加协议遵循者
 extension SomeType: SomeProtocol, AnotherProcotol {
 }
 */

//计算属性
extension Double {
    var km:Double {
        return self * 1_000
    }
    var m: Double {
        return self
    }
    var cm: Double {
        return self / 100.0
    }
}

let oneInch = 24.5.cm
let kilometer = 1.km
let aMarhton = 42.km + 5.m

//构造器 只能为类添加便利构造器
struct Size {
    var width = 0.0, height = 0.0
}

struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    var orign:Point = Point()
    var size:Size = Size()
}

let defautrect = Rect()

let memberwiserect = Rect(orign: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))

extension Rect {
    init(center: Point, size: Size) {
        let originX = center.x - size.width / 2
        let originY = center.y - size.height / 2
        self.init(orign: Point(x:originX, y:originY), size: size)
    }
}
        
let rect =  Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))

//方法
extension Int {
    func repetion(task: () -> Void) {
        for i in 0..<self {
            task()
        }
    }
}
         
3.repetion {
    print("hello")
}

//修改实例方法
extension Int {
    mutating func square() { //在结构体和枚举中修改self，或其属性的方法必须将该实例方法标注为mutating
       self = self * self
    }
}

var aValue = 3
    aValue.square()

//下标
extension Int {
    subscript(digitalInex: Int) -> Int {
        var index = digitalInex
        var decimalBase = 1
        while index > 0 {
            decimalBase *= 10
            index -= 1
        }
        return (self / decimalBase) % 10
    }
}

746381295[0]
746381295[1]
746381295[2]
746381295[8]
746381295[9]

//嵌套类型
extension Character {
    enum Kind {
    case Vowel, Consnant, Other
    }
    
    var kind:Kind {
        switch String(self).lowercased() {
        case "a", "e", "i" , "o", "u":
            return .Vowel
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q","r","s":
            return .Consnant
        default:
            return .Other
        }
    }
}

func printLetterKinds(word:String) {
    for char in word {
        switch char.kind {
        case .Vowel:
            print("vowel")
        case .Consnant:
            print("consonant")
        case .Other:
            print("others")
        }
    }
}


printLetterKinds(word: "hello")
